package com.tools.middle.elasticsearch;

import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch.core.search.HighlightField;
import com.tools.common.container.OwnPairs;
import com.tools.common.object.Note;
import com.tools.common.thread.Timeunit;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 在多个索引上多 ID 搜索
 * 继承父类的方法在多条件查询时不起作用（除了分词器）
 * */
@Note("在多个索引上多 ID 搜索。" +
        "继承父类的方法在多条件查询时不起作用（除了分词器）")
public final class IdsSearch extends Search {

    @Note("文档 ID 列表")
    private List<String> ids;

    /* **********************************************************************************
     *
     *          构造器
     *
     * *********************************************************************************
     * */

    public IdsSearch() {}

    public static IdsSearch of() {
        return new IdsSearch();
    }

    /* **********************************************************************************
     *
     *          Getter / Setter
     *
     * *********************************************************************************
     * */

    public List<String> getNewIds() {
        return (ids == null || ids.isEmpty())
                ? new ArrayList<>()
                : new ArrayList<>(ids);
    }

    List<String> getIds() {
        return ids;
    }

    public void setIds(String id) {
        private_idNotEmpty(id);
        this.ids = new ArrayList<>(1);
        this.ids.add(id);
    }

    public void setIds(String... ids) {
        int length = default_getArrayLength(ids);
        if(length == 0) return;
        this.ids = new ArrayList<>(length);
        for (String id : ids) {
            private_idNotEmpty(id);
            this.ids.add(id);
        }
    }

    public void setIds(Iterable<String> ids) {
        if(ids == null) return;
        if(ids instanceof List) {
            for (String id : ids) private_idNotEmpty(id);
            this.ids = (List<String>) ids;
            return;
        }
        int size = default_getIterableSize(ids);
        if(size == 0) return;
        this.ids = new ArrayList<>(size);
        for (String id : ids) {
            private_idNotEmpty(id);
            this.ids.add(id);
        }
    }

    @Override
    public String toString() {
        return "IdsSearch{" +
                "ids=" + ids +
                ", " + super.toString() +
                '}';
    }


    /* **********************************************************************************
     *
     *          链式方法
     *
     * *********************************************************************************
     * */

    public IdsSearch ids(String id) {
        this.setIds(id);
        return this;
    }

    public IdsSearch ids(String... ids) {
        this.setIds(ids);
        return this;
    }

    public IdsSearch ids(Iterable<String> ids) {
        this.setIds(ids);
        return this;
    }

    @Override
    public IdsSearch indicesNames(String indicesName) {
        super.setIndicesNames(indicesName);
        return this;
    }

    @Override
    public IdsSearch indicesNames(String... indicesNames) {
        super.setIndicesNames(indicesNames);
        return this;
    }

    @Override
    public IdsSearch indicesNames(Iterable<String> indicesNames) {
        super.setIndicesNames(indicesNames);
        return this;
    }

    @Override
    public IdsSearch timeout(String timeout) {
        super.setTimeout(timeout);
        return this;
    }

    @Override
    public IdsSearch timeout(int timeout, Timeunit timeunit) {
        super.setTimeout(timeout, timeunit);
        return this;
    }

    @Override
    public IdsSearch analyzer(String analyzer) {
        super.setAnalyzer(analyzer);
        return this;
    }

    @Override
    public IdsSearch from(int from) {
        super.setFrom(from);
        return this;
    }

    @Override
    public IdsSearch size(int size) {
        super.setSize(size);
        return this;
    }

    @Override
    public IdsSearch sorts(String field, SortOrder order) {
        super.sorts(field, order);
        return this;
    }

    @Override
    public IdsSearch sorts(Map<String, SortOrder> fieldAndOrders) {
        super.sorts(fieldAndOrders);
        return this;
    }

    @Override
    public IdsSearch sorts(OwnPairs<String, SortOrder> fieldAndOrders) {
        super.sorts(fieldAndOrders);
        return this;
    }

    @Override
    public IdsSearch includes(String includeField) {
        super.includes(includeField);
        return this;
    }

    @Override
    public IdsSearch includes(String... includeFields) {
        super.includes(includeFields);
        return this;
    }

    @Override
    public IdsSearch includes(Iterable<String> includeFields) {
        super.includes(includeFields);
        return this;
    }

    @Override
    public IdsSearch excludes(String excludeField) {
        super.excludes(excludeField);
        return this;
    }

    @Override
    public IdsSearch excludes(String... excludeFields) {
        super.excludes(excludeFields);
        return this;
    }

    @Override
    public IdsSearch excludes(Iterable<String> excludeFields) {
        super.excludes(excludeFields);
        return this;
    }

    @Override
    public IdsSearch aggregations(String field, Aggregation agg) {
        super.aggregations(field, agg);
        return this;
    }

    @Override
    public IdsSearch aggregations(Map<String, Aggregation> aggregations) {
        super.aggregations(aggregations);
        return this;
    }

    @Override
    public IdsSearch aggregations(OwnPairs<String, Aggregation> aggregations) {
        super.aggregations(aggregations);
        return this;
    }

    @Override
    public IdsSearch highlights(String field, HighlightField highlightField) {
        super.highlights(field, highlightField);
        return this;
    }

    @Override
    public IdsSearch highlights(Map<String, HighlightField> highlights) {
        super.highlights(highlights);
        return this;
    }

    @Override
    public IdsSearch highlights(OwnPairs<String, HighlightField> highlights) {
        super.highlights(highlights);
        return this;
    }

    /* **********************************************************************************
     *
     *          自定义方法
     *
     * *********************************************************************************
     * */

    public IdsSearch addId(String id) {
        private_idNotEmpty(id);
        private_initIds(1);
        this.ids.add(id);
        return this;
    }

    public IdsSearch addIds(String... ids) {
        if(ids == null) return this;
        int length = default_getArrayLength(ids);
        if(length == 0) return this;
        private_initIds(length);
        for (String id : ids) {
            private_idNotEmpty(id);
            this.ids.add(id);
        }
        return this;
    }

    public IdsSearch addIds(Iterable<String> ids) {
        if(ids instanceof List) {
            for (String id : ids) private_idNotEmpty(id);
            this.ids = (List<String>) ids;
            return this;
        }
        if(ids == null) return this;
        int size = default_getIterableSize(ids);
        if(size == 0) return this;
        private_initIds(size);
        for (String id : ids) {
            private_idNotEmpty(id);
            this.ids.add(id);
        }
        return this;
    }

    public IdsSearch modifyId(int index, String id) {
        if(ids != null && !ids.isEmpty() && !default_indexCheck(index, ids.size())) this.ids.set(index, id);
        return this;
    }


    public IdsSearch removeId(String id) {
        if(ids == null || ids.isEmpty()) return this;
        this.ids.remove(id);
        return this;
    }

    public IdsSearch removeId(int index) {
        if(ids != null && !ids.isEmpty() && !default_indexCheck(index, ids.size())) this.ids.remove(index);;
        return this;
    }

    public IdsSearch removeIds(String... ids) {
        if(ids == null || ids.length == 0) return this;
        for (String id : ids) this.ids.remove(id);
        return this;
    }

    public IdsSearch removeIds(Iterable<String> ids) {
        if(ids == null) return this;
        for (String id : ids) this.ids.remove(id);
        return this;
    }

    public String getId(int index) {
        if(ids != null && !ids.isEmpty() && !default_indexCheck(index, ids.size())) return ids.get(index);
        return null;
    }

    public int idsSize() {
        return (ids == null) ? 0 : ids.size();
    }

    public boolean containsId(String id) {
        return ids != null && !ids.isEmpty() && this.ids.contains(id);
    }

    @Override
    public IdsSearch addIndicesName(String indicesName) {
        super.addIndicesName(indicesName);
        return this;
    }

    @Override
    public IdsSearch addIndicesNames(String... indicesNames) {
        super.addIndicesNames(indicesNames);
        return this;
    }

    @Override
    public IdsSearch addIndicesNames(Iterable<String> indicesNames) {
        super.addIndicesNames(indicesNames);
        return this;
    }

    @Override
    public IdsSearch modifyIndicesName(int index, String indicesName) {
        super.modifyIndicesName(index, indicesName);
        return this;
    }

    @Override
    public IdsSearch removeIndicesName(String indicesName) {
        super.removeIndicesName(indicesName);
        return this;
    }

    @Override
    public IdsSearch removeIndicesName(int index) {
        super.removeIndicesName(index);
        return this;
    }

    @Override
    public IdsSearch removeIndicesNames(String... indicesNames) {
        super.removeIndicesNames(indicesNames);
        return this;
    }

    public IdsSearch removeIndicesNames(Iterable<String> indicesNames) {
        super.removeIndicesNames(indicesNames);
        return this;
    }

    @Override
    public IdsSearch addSort(String field, SortOrder order) {
        super.addSort(field, order);
        return this;
    }

    @Override
    public IdsSearch addSorts(Map<String, SortOrder> fieldAndOrders) {
        super.addSorts(fieldAndOrders);
        return this;
    }

    @Override
    public IdsSearch addSorts(OwnPairs<String, SortOrder> fieldAndOrders) {
        super.addSorts(fieldAndOrders);
        return this;
    }

    @Override
    public IdsSearch modifySort(int index, String field, SortOrder order) {
        super.modifySort(index, field, order);
        return this;
    }

    @Override
    public IdsSearch clearSorts() {
        super.clearSorts();
        return this;
    }

    @Override
    public IdsSearch removeSort(String field, SortOrder order) {
        super.removeSort(field, order);
        return this;
    }

    @Override
    public IdsSearch removeSort(int index) {
        super.removeSort(index);
        return this;
    }

    @Override
    public IdsSearch removeSorts(Map<String, SortOrder> fieldAndOrders) {
        super.removeSorts(fieldAndOrders);
        return this;
    }

    @Override
    public IdsSearch removeSorts(OwnPairs<String, SortOrder> fieldAndOrders) {
        super.removeSorts(fieldAndOrders);
        return this;
    }


    @Override
    public IdsSearch addInclude(String field) {
        super.addInclude(field);
        return this;
    }

    @Override
    public IdsSearch addIncludes(String... fields) {
        super.addIncludes(fields);
        return this;
    }

    @Override
    public IdsSearch addIncludes(Iterable<String> fields) {
        super.addIncludes(fields);
        return this;
    }

    @Override
    public IdsSearch modifyInclude(int index, String field) {
        super.modifyInclude(index, field);
        return this;
    }

    @Override
    public IdsSearch clearIncludes() {
        super.clearIncludes();
        return this;
    }

    @Override
    public IdsSearch removeInclude(String field) {
        super.removeInclude(field);
        return this;
    }

    @Override
    public IdsSearch removeInclude(int index) {
        super.removeInclude(index);
        return this;
    }

    @Override
    public IdsSearch removeIncludes(String... fields) {
        super.removeIncludes(fields);
        return this;
    }

    @Override
    public IdsSearch removeIncludes(Iterable<String> fields) {
        super.removeIncludes(fields);
        return this;
    }

    @Override
    public IdsSearch addExclude(String field) {
        super.addExclude(field);
        return this;
    }

    @Override
    public IdsSearch addExcludes(String... fields) {
        super.addExcludes(fields);
        return this;
    }

    @Override
    public IdsSearch addExcludes(Iterable<String> fields) {
        super.addExcludes(fields);
        return this;
    }

    @Override
    public IdsSearch modifyExclude(int index, String field) {
        super.modifyExclude(index, field);
        return this;
    }

    @Override
    public IdsSearch clearExcludes() {
        super.clearExcludes();
        return this;
    }

    @Override
    public IdsSearch removeExclude(String field) {
        super.removeExclude(field);
        return this;
    }

    @Override
    public IdsSearch removeExclude(int index) {
        super.removeExclude(index);
        return this;
    }

    @Override
    public IdsSearch removeExcludes(String... fields) {
        super.removeExcludes(fields);
        return this;
    }

    @Override
    public IdsSearch removeExcludes(Iterable<String> fields) {
        super.removeExcludes(fields);
        return this;
    }

    @Override
    public IdsSearch addAgg(String field, Aggregation agg) {
        super.addAgg(field, agg);
        return this;
    }

    @Override
    public IdsSearch addAggs(Map<String, Aggregation> aggs) {
        super.addAggs(aggs);
        return this;
    }

    @Override
    public IdsSearch addAggs(OwnPairs<String, Aggregation> aggs) {
        super.addAggs(aggs);
        return this;
    }

    @Override
    public IdsSearch clearAggs() {
        super.clearAggs();
        return this;
    }

    @Override
    public IdsSearch removeAgg(String field) {
        super.removeAgg(field);
        return this;
    }

    @Override
    public IdsSearch removeAgg(String... fields) {
        super.removeAgg(fields);
        return this;
    }

    @Override
    public IdsSearch removeAgg(Iterable<String> fields) {
        super.removeAgg(fields);
        return this;
    }

    @Override
    public IdsSearch addHighlight(String field, HighlightField highlightField) {
        super.addHighlight(field, highlightField);
        return this;
    }

    @Override
    public IdsSearch addHighlights(Map<String, HighlightField> highlights) {
        super.addHighlights(highlights);
        return this;
    }

    @Override
    public IdsSearch addHighlights(OwnPairs<String, HighlightField> highlights) {
        super.addHighlights(highlights);
        return this;
    }

    @Override
    public IdsSearch clearHighlight() {
        super.clearHighlight();
        return this;
    }

    @Override
    public IdsSearch removeHighlight(String field) {
        super.removeHighlight(field);;
        return this;
    }

    @Override
    public IdsSearch removeHighlights(String... fields) {
        super.removeHighlights(fields);
        return this;
    }

    @Override
    public IdsSearch removeHighlights(Iterable<String> fields) {
        super.removeHighlights(fields);
        return this;
    }



    /* **********************************************************************************
     *
     *          私有逻辑
     *
     * *********************************************************************************
     * */

    @Note("文档 ID 的非空校验")
    private static void private_idNotEmpty(String id) {
        if(id == null || id.isEmpty()) throw new NullPointerException("文档 ID 名称不能为空");
    }

    @Note("初始化文档 ID 列表")
    private void private_initIds(int initSize) {
        if(ids == null) this.ids = new ArrayList<>(initSize);
    }
}
